home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus Leser 15
/
Amiga Plus Leser CD 15.iso
/
Tools
/
Development
/
mmu
/
MuManual
/
Autodocs
/
mmures.doc
< prev
Wrap
Text File
|
2002-03-12
|
73KB
|
2,101 lines
TABLE OF CONTENTS
mmu.resource/--Background--
mmu.resource/--Background-- mmu.resource/--Background--
PURPOSE
The mmu.resource is the low-level driver of the mmu.library;
it is just one level above hardware and is the interface of
the mmu.library to the hardware. There is absolutely no need
to make use of this resource whatsoever; the calling syntax is
wierd and requires assembly language necessarely. Many things
within this resource work much different than you might expect.
In case the mmu.resource is found available when the mmu.library
is opened, the library will use the resource to get its dirty
work done. That is, the construction of the MMU table descriptors,
the exception handler and similar. If the mmu.resource is not
found active, the mmu.library tries to figure this out itself.
It will check for the available routine and will use internal
routines that provide similar functions than the resource. It
will not try to build a mmu.resource, though.
The mmu.resource could be used to make use of the mmu.library
in an environment that is not supported by the library initially,
as for example more advanced processors, external MMUs or even
"software emulated" MMUs for emulators. Writing a mmu.resource
for a non-68K MMU might be possible provided the programming
model of this CPU is close enough to that of the Motorola's.
In order to make the mmu.library use your resource routines,
your hardware/software should make the resource available on
boot-up by means of AddResource() before the mmu.library gets
loaded.
The calling syntax of the mmu.resource is, indeed, strange.
This is because most of its functions are used by the core
code of the mmu.library, and hence must expect the a6 register
loaded with the base pointer of the mmu.library, and not this
resource. Some calls require multiple return values in several
registers, or even the condition-code register. About the only
reason why this is so is speed, and tradition - as to mimic the
former calling syntax of the mmu.library internal routines.
Even though the mmu.resource is just a resource, the typical
library type entries LibOpen(), LibClose(), LibExpunge() and
LibExtFunc() should be available. They are currently not used,
though.
mmu.resource/CheckMMUInterface mmu.resource/CheckMMUInterface
NAME
CheckMMUInterface - check for the required API interface level
SYNOPSIS
okflag = CheckMMUInterface( version, mmubase, mmuresbase );
d0 d0 a0 a6
BOOL CheckMMUInterface( UWORD, struct MMUBase *, struct MMUResBase);
FUNCTION
Checks whether the expected API level of the mmu.resource matches
the requirements of the mmu.library and delivers the mmu.library
base pointer to the resource.
INPUTS
version - the version number of the mmu.resource API the mmu.library
expects to be available. This need not to coincide with the version of
the mmu.library, though.
mmubase - base pointer of the mmu.library based for internal use of
the resource.
mmuresbase - base pointer of the resource itself.
RETURNS
TRUE in case the resource can service the API whose version is
indicated by the "version" argument; FALSE otherwise.
NOTES
Note that the API version of the mmu.library need not to coincide
with its library version. The lowest available API level of the
library is 43; you should currently check for this value and fail
if you get anything different. Future versions of the mmu.library
might require an enhanced interface and will then bump this
release number.
This function will be called first by the mmu.library as soon as
it detects that the mmu.resource is available. If the result
value is FALSE, the mmu.library will revert to its own internal
CPU/MMU check and will try to select a proper internal set of
support routines.
BUGS
SEE ALSO
mmu.resource/MMUResType mmu.resource/MMUResType
NAME
MMUResType - provide a one-byte identifier specifying the
MMU type that gets supported
SYNOPSIS
type = MMUResType( mmuresbase );
d0 a6
char MMUResType( struct MMUResBase * );
FUNCTION
Returns the ID of the mmu that is supported by this resource. This
number will be forwarded to application programs by means of the
mmu.library call GetMMUType().
INPUTS
mmuresbase - a pointer to the mmu.resource base.
RETURNS
an identifier specifying the mmu that is available.
NOTES
BUGS
SEE ALSO
mmu.library/GetMMUType()
mmu.resource/AdjustCtxtSettings mmu.resource/AdjustCtxtSettings
NAME
AdjustCtxtSettings - optimize a MMUContext for best performance
SYNPOSIS
okflag = AdjustCtxtSettings( ctxt, mmubase );
d0 a5 a6
BOOL AdjustCtxtSettings( struct IMMUContext *, struct MMUBase *);
FUNCTION
This function is called after the mmu.library identified the
initial MMU profile by means of ReadMMUConfig(). It is supposed
to modify the read ctxt->ctx_LevelxBits, ctxt->PageBits and
ctxt->ctx_InitialShift bits in the following way, guaranteeing
that the sum of all these bit counters remains 32 - the number of
bits required to address the full address range of the MC68K
processor.
- the initial shift must be arranged to be zero by possibly
enlarging the number of bits in the levels below.
- the page size should be adjusted to a reasonable default
value if it is supposed to be non-sensical. This depends on
your own choice, but as the mmu.library gets rather un-
effective for small pages, page sizes below 1K and above 8K
should possibly be avoided.
INPUTS
ctxt - a pointer to the IMMUContext structure to be modified.
mmubase - base pointer of the mmu.library.
RESULTS
a TRUE/FALSE indicator telling the mmu.library whether the
resource was successful to establish a useable setting.
NOTES
Note that a6 is loaded with the base of the mmu.library, not
that of the resource.
This function need not to update all the mask values of the
IMMUContext. This is done by the library internally afterwards.
The internal mmu.library drivers do not try to modify the page
size, except for the 68030 and 68851 drivers which will reject
to use a page size smaller than 1K and will then use a default
setting. It is probably a good idea to use the same approach
to come to a useful MMU setup.
BUGS
SEE ALSO
ReadMMUConfig()
mmu.resource/ReadMMUConfig mmu.resource/ReadMMUConfig
NAME
ReadMMUConfig() - read out the MMU register setup
SYNOPSIS
ReadMMUConfig( config, mmubase );
a0 a6
void ReadMMUConfig(struct MMUConfig *, struct MMUBase *);
FUNCTION
Reads all relevant MMU hardware registers and fills them into
the IMMUConfig structure for further processing.
INPUTS
config - pointer to the struct MMUConfig to fill out.
mmubase - base pointer to the mmu.library
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This call need not to make a complete backup of the MMU setup;
only those registers that are relevant for the MMU programming
model need to be saved. The meaning of the components of the
MMUConfig structure are, even though documented, up to you and
the hardware requirements.
This function is called in supervisor mode and should return
to the caller with an RTS.
BUGS
SEE ALSO
mmu/config.h,WriteMMUConfig(),BuildMMUConfig()
mmu.resource/WriteMMUConfig mmu.resource/WriteMMUConfig
NAME
WriteMMUConfig() - load an MMU configuration into the hardware
SYNOPSIS
WriteMMUConfig( config, mmubase );
a0 a6
void WriteMMUConfig(struct MMUConfig *, struct MMUBase *);
FUNCTION
Writes the configuration described by the struct MMUConfig into
the hardware and flushes caches as required.
INPUTS
config - pointer to a struct MMUConfig to be loaded into the
hardware
mmubase - pointer to the mmu.library base.
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This call installs all relevant data of the MMUConfig back into
the hardware; dependent on the MMU, various caches must be
flushed here as well. The suggested operation works as follows:
- interrupts should be disabled by writing into the sr
- caches should be pushed back if required
- the MMU should be disabled,
- address translation caches should be flushed,
- transparent translation should be installed,
- MMU root pointers should be installed,
- MMU translation registers should be installed,
- caches should be flushed/pushed again.
This function is called in supervisor mode, it should return to
the caller by means of an RTS.
The function may leave interrupts disabled; they will be re-
enabled as soon as the supervisor mode is left by the caller.
This call need not to install all registers; only the registers
that are relevant to the MMU programming model are required to
be written back.
On a context switch, the mmu.library will compare all components
of the MMUContext except the two (user/supervisor) root pointers.
If these extended registers are equal, a short context switch by
means of LoadRoot() is engaged; otherwise, a complete context
switch by this function will be run.
BUGS
SEE ALSO
mmu/config.h,ReadMMUConfig(),BuildMMUConfig(),LoadRoot()
mmu.resource/BuildMMUConfig mmu.resource/BuildMMUConfig
NAME
BuildMMUConfig() - build a new MMU configuration from templates
SYNOPSIS
ok = BuildMMUConfig( uctx, sctx, defconfig, destconfig, mmubase);
d0 a0 a1 a2 a3 a6
BOOL BuildMMUConfig(struct IMMUContext *, struct IMMUConctext *,
struct MMUConfig *,struct MMUConfig *,
struct MMUBase *);
FUNCTION
Fills in a new struct MMUConfig by combining data from the default
configuration, the user and the supervisor context. This function
is called by the mmu.library whenever the configuration of a new
context must be created. It should write the MMU root pointers of
the user and supervisor contexts into the MMUConfig, and fill the
remaining data of the configuration with default values from the
default configuration.
INPUTS
uctx - the user context whose configuration should be build. This
shall be the origin of the user root pointer. Further, the
page layout shall be taken from the uctx->ctx_LevelABits...
uctx->ctx_LevelDBits, uctx->ctx_PageBits bits and should
modify the translation control provided by defconfig ac-
cordingly before this data goes into the translation control
of destconfig.
Further, this procedure should clear transparent translation
if the uctx->ctx_Flags say so.
sctx - the supervisor context of the uctx. This is the origin of the
supervisor root pointer.
defconfig - the default MMU configuration that was read by the
mmu.library on startup. Remaining registers of the MMU
programming model should be taken from here.
destconfig - destination MMU configuration to fill out.
mmubase - pointer to the mmu.library base.
RESULTS
a boolean success/failure indicator. Should return TRUE in case
the configuration could be build successfully, FALSE otherwise
if for example the page configuration specified by the context is
not available.
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
BUGS
SEE ALSO
mmu/config.h,ReadMMUConfig(),WriteMMUConfig()
mmu.library/LoadRoot mmu.library/LoadRoot
NAME
LoadRoot() - perform a minor context switch
SYNOPSIS
LoadRoot( uroot, sroot, mmubase);
a0 a1 a6
void LoadRoot( void *, void *, struct MMUBase *);
FUNCTION
Performs a minor context switch by exchanging user, supervisor or
both MMU root pointers.
INPUTS
uroot - the user MMU root pointer or NULL in case the user root
pointer shall remain unaltered.
sroot - the supervisor MMU root pointer or NULL in case it need not
to be touched.
mmubase - pointer to the mmu.library base.
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This function installs either a new user or supervisor root pointer
into the MMU hardware; therefore, this function is called within
supervisor mode and shall return with an RTS to the user.
This function shall perform the following operations:
- flush the address translation cache,
- flush/push the cache if the cache is logically indexed. A
physically indexed cache need not to be pushed.
- load the user root pointer with the new value
- flush old user root pointer from a RTC, if available,
and old user root<>new user root
- load the supervisor root pointer with the new value,
- flush old supervisor pointer from a RTC, if available,
and old supervisor root<>new supervisor root
- flush the ATC again
The mmu.library calls either this function or WriteMMUConfig()
on a context switch. If the MMU registers of old and new context
are identically except for user and supervisor root pointer,
a minor context switch is run by this function. Otherwise, a
major context switch by means of WriteMMUConfig() is performed.
BUGS
SEE ALSO
WriteMMUConfig()
mmu.resource/DefineMMUContext mmu.resource/DefineMMUContext
NAME
DefineMMUContext() - fill IMMUContext components with MMU specific
data from a MMUConfig.
SYNOPSIS
DefineMMUContext( config, ctxt, mmubase);
a0 a5 a6
void DefineMMUConfig( struct MMUConfig *, struct IMMUContext *,
struct MMUBase *);
FUNCTION
Reads data from the MMUConfig structure, interprets the page
layout defined by this data and places the results in the
IMMUContext pointed to by ctxt. This function shall fill
in:
ctxt->ctx_InitialShift with the initial shift value
ctxt->ctx_LevelABits with the number of address bits to
address level A of the MMU table.
ctxt->ctx_LevelBBits
ctxt->ctx_LevelCBits
ctxt->ctx_LevelDBits ditto up to level D
ctxt->ctx_PageBits number of bits of a logical address
that define the offset within a page.
If the MMU is disabled, the above should be set to reasonable
defaults, as for example 4K pages.
ctxt->ctx_LevelAAlign Page alignment alá AllocAligned() that
is required for the level A descriptor
level. This must be a power of two.
ctxt->ctx_LevelBAlign
ctxt->ctx_LevelCAlign
ctxt->ctx_LevelDAlign ditto for levels B..D
ctxt->ctx_DescriptorAlign alignment restrictions for
indirect descriptors.
ctxt->ctx_PageMemMask binary mask of all mapping properties that
shall be touched when allocating memory for
the MMU table.
ctxt->ctx_PageMemProp binary mask of page properties that will be
enabled/disabled for memory allocated for MMU
page descriptors.
The above two are only kept care of if the user specified
DescriptorCacheInhibit ON
in the ENVARC:MMU-Configuration file. Then, the properties of mmu
page memory are filtered by
newprops = oldprops & (~PageMemMask) | PageMemProps
to get the new property flags for the MMU table memory. Otherwise,
these two are ignored.
ctxt->ctx_PageMemForbid property flags that must not be set for memory
that got allocated for the MMU table.
If the mmu.library finds one of the above properties set for memory
that it allocated, it will guru. Typically, this mask should contain:
MAPP_BLANK, MAPP_INVALID, MAPP_SWAPPED, MAPP_TRANSLATED, MAPP_ROM,
MAPP_WRITEPROTECTED, MAPP_BUNDLED, MAPP_SUPERVISORONLY, MAPP_INDIRECT
Note that memory allocated by MEMF_PUBLIC should never have any of the
properties above. Note further that the mmu.library is able to work
with MAPP_REMAPPED memory for mmu descriptors since it will first
translate the physical address to logical before using it for the
descriptors. This requires, though, that the memory is always
accessable under its physical address as well.
ctxt->ctx_LargestPageSize largest possible page size with
this MMU; not necessarely the
active page size.
This value is required by the mmu.library to compute the
RemapSize() value. It should be a power of two.
INPUTS
config - struct MMUConfig to be read out.
ctxt - struct IMMUContext to be filled in.
mmubase - library base of the mmu.library.
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is called by the mmu.library whenever a new context must be
build; you need not to touch any other mask/flags fields of the
IMMUContext as the library will compute them itself from the
data you provided. Note further that you should not cheat here
with the settings to get a more reasonable setup. The mmu.library
will later on call AdjustCtxtSetting() on this context to give
you the chance to make some adjustments on the MMU setup.
DefineMMUContext( config, ctxt, mmubase);
a0 a5 a6
void DefineMMUConfig( struct MMUConfig *, struct IMMUContext *,
struct MMUBase *);
BUGS
SEE ALSO
AdjustCtxtSetting(), mmu/RemapSize(), mmu/context.h,
mmu/config.h
mmu.resource/AdjustMMUContext mmu.resource/AdjustMMUContext
NAME
AdjustMMUContext() - integrate user supplied page layout settings into
an IMMUContext
SYNOPSIS
errcode = AdjustMMUContext( depth, destctxt, parent , mmubase );
d0 d0 a0 a1 a6
LONG AdjustMMUContext( LONG depth, struct MMUContext *,
struct IMMUContext *, struct IMMUBase *);
FUNCTION
This function gets called on CreateMMUContextA() to integrate
the user supplied page model into the context, given a parent/
template context to take default settings from. This function
shall try to find a possible page configuration fit for the user
supplied data within the destctxt, or shall fail if it is not
possible to generate the user defined page layout.
INPUTS
depth - depth of the MMU tree in levels, or negative if not
specified by the user. Then, this function shall use
the default depth from the "parent" context.
destctxt - destination context to generate a page layout for;
specifically, the destctxt->ctx_LevelABits to
destctxt->ctx_PageBits must be defined. Initially,
these are either filled with the user-specified values,
or 0xff for "default values". It is the job of this
function to fill all the components of the IMMUContext
that are set to 0xff such that the page layout is
supported by the hardware and as close as possible to
that of the parent. Ideally, the parent configuration
should be used to allow minor context switches between
the parent and this context. If possible, at least the
page size of parent and destctxt should be made identically,
unless the user tries to setup its own page size.
parent - struct IMMUContext to take default settings from.
mmubase - library base pointer of the mmu.library
RESULTS
An error code or zero on success. The following error codes shall
be used:
CCERR_INVALID_PARAMETERS the parameters make no sense, as
for example the sum of all level and
page bits is not 32.
CCERR_UNSUPPORTED the parameters are consistent, but not
supported by the MMU hardware.
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
BUGS
SEE ALSO
mmu/context.h, mmu/CreateMMUContextA()
mmu.resource/ParseTT mmu.resource/ParseTT
NAME
ParseTT() - integrate the transparent translation registers into
the MMU table layout.
SYNOPSIS
ok = ParseTT( ctxt, config, mmubase);
d0 a0 a1 a6
BOOL ParseTT( struct IMMUContext *, struct MMUConfig *, struct MMUBase *);
FUNCTION
Parses the transparent translation registers given by the MMUConfig
and integrates the definitions made by the TTx registers into the
MMU setup defined by the ctxt. The attempt of this function is to
get rid of the TTx definitions and mimic their function by placing
similar page definition data into the MMU table of the context.
INPUTS
ctxt - the IMMUContext into which the TTx registers shall be integrated.
Especially, the following flags in ctxt->ctx_Flags should be
considered:
CTXF_CLEARDTT0 Is set on entry if the DTT0 register
shall be ignored.
This flag gets set by the mmu.library on startup if the
ENVARC:MMU-Configuration contains the "ClearTTx" command.
On exit, this flag shall be set in case the DTT0 setup could
be successfully integrated into the MMU table of ctxt.
CTXF_CLEARDTT1, CTXF_CLEARITT0, CTXF_CLEARITT1
similar.
config - struct MMUConfig containing the current setup of the TTx
registers that are about to be integrated.
mmubase - pointer to the mmu.library base
RESULTS
a boolean success/failure indicator.
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This function might require the help of two internal mmu.library
functions that are hereby documented purely for the use of the
mmu.resource:
ok = AddTransparentTranslation( ctxt, amask, props, propmask );
d0 a5 a1 d0 d1
BOOL AddTransparentTranslation( struct IMMUContext *, UWORD,
ULONG, ULONG );
ok = OrTransparentTranslation( ctxt, amask, props, propmask );
BOOL OrTransparentTranslation( struct IMMUContext *, UWORD,
ULONG, ULONG );
Both functions work very much the like with the difference that
the first attempts to insert all TTx properties into the context,
whereas the second uses the most conservative setting when the
old context definition and the TTx definition conflict.
Arguments of these calls are as follows:
ctxt - MMUContext to integrate TTx settings into
amask - an address and address mask. The lower 8 bits
of amask define a mask, the upper 8 an address.
The address mask is interpreted as bits 31..24 of a full mask,
where a one-bit indicates that the corresponding address bit is
ignored on address comparison. Bits 23..0 are always understood
to be one, i.e. are always ignored. Hence, TTx registers are
limited to define 16MB chunks of memory at once.
The address bits define bits 31..24 of an address to compare
against.
The code will, therefore, perform the following operation:
if (((address>>24)^(amask >> 8)) & (~amask & 0xff) == 0) {
/* modify context */
}
If the above comparison is true, the mmu.library will modify
the 16MB segment starting at "address" by means of the propmask
and the props arguments. "props" defines the new values of the
property flags, "propmask" which property bits are to be
altered.
BUGS
SEE ALSO
mmu/context.h
mmu.resource/RootStarter mmu.resource/RootStarter
NAME
RootStarter - get a pointer to the MMU root as abstract table
descriptor
SYNOPSIS
ok = RootStarter( config, atd, type, mmubase);
d0 a1 a0 d0 a6
LONG RootStarter(struct MMUConfig *,struct AbstractDescriptor *,
UBYTE, struct MMUBase *);
FUNCTION
Fills in the "AbstractDesctriptor" describing the location of the
MMU root table pointer. adt->adt_Pointer should be filled with
the address(!) of a memory location containing the user or
superivor root table pointer. This is typically the address of
one of the root pointer components within the MMUConfig passed
in.
INPUTS
config - struct MMUConfig containing the user and supervisor
root pointers.
atd - AbstractDescriptor to be filled in. The following
fields must be provided:
atd->atd_Pointer pointer to the root pointer
atd->atd_LowerLimit set to zero
atd->atd_UpperLimit set to zero
atd->atd_Type set to ATDT_TABLE for short
descriptors (four bytes),
ATDT_TABLE|ATDT_LONG for long
descriptors (eight bytes)
type - 0 if you need to provide the user root pointer, non-
zero otherwise. In case the MMU programming model described
by "config" does not distinguish between user and supervisor
access, ignore this type.
mmubase - pointer to the mmu.library base.
RESULTS
ok should be set to zero in case the MMU root could not be read.
In this case, the resource will have caused a guru already.
The result code shall be -1 in case the MMU is enabled and the
root could be read, and +1 in case the MMU is disabled. The
atd need not to be filled out in this case.
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This function is used by the mmu.library to initiate the mmu table
scan of the active MMU configuration.
BUGS
SEE ALSO
ReadDescriptor(), mmu/config.h, mmu/descriptor.h
mmu.resource/ReadDescriptor mmu.resource/ReadDescriptor
NAME
ReadDescriptor() - read and interpret an hardware MMU descriptor
SYNOPSIS
ReadDescriptor( deptr, atd, type, level, ctxt, mmubase );
a1 a0 d0 d1 a5 a6
ReadDescriptor( ULONG *, struct AbstractDescriptor *, UBYTE ,
UBYTE, struct IMMUContext *, struct MMUBase *);
FUNCTION
Reads and interprets an MMU table/page descriptor pointed to by
deptr, and fills the abstraction data into the atd.
INPUTS
deptr - points to the descriptor to read.
atd - the AbstractDescriptor to be filled in.
type - type of the descriptor to be read. This has the bit
ATDB_LONG set for long descriptors. All other bits
shall be ignored.
level - MMU table level to read the descriptor from. Zero
identifies level A, -1 is used in case this function
shall read and interpret the root pointer itself, as
supplied by RootStarter(). "deptr" points then to a
memory location containing(!) the root pointer.
ctxt - struct IMMUContext this parsing is done within. The
IMMUContext provides all bitmasks to isolate property
bits and pointers from the descriptor, i.e. in
ctxt->ctx_LevelAMask...ctxt->ctx_PageMask. Note that
the LevelAMask is required for reading pointers that
point to a level A table, i.e. the root pointer.
mmubase - pointer to the mmu.library base.
The AbstractDescriptor must be filled in as follows:
atd->atd_Pointer pointer to the next MMU descriptor table
or the physical page address or the
indirect descriptor.
atd->atd_Properties properties described by this descriptor.
atd->atd_LowerLimit in case this is a long descriptor, the
lower page limit in case this descriptor
uses a lower limit, or zero otherwise.
atd->atd_UpperLimit in case this descriptor is long and uses
an upper page limit, fill this limit into
here without the "upper limit signal bit".
Otherwise, set to 0x7fff.
atd->atd_ThisType type of this descriptor. The following bits
are available to signal the type:
ATDB_TABLE is a table descriptor
ATDB_INDIRECT is an indirect descriptor
ATDB_PAGE is a page descriptor
(includes early termination descriptors)
ATDB_INVALID is an invalid descriptor
(set properties to MAPP_INVALID, too!)
atd->atd_NextType type of the descriptors this descriptor
points to if this is a table or an invalid
descriptor. The following bits should be
set:
ATDB_LONG Descriptors in the table this descriptor
points to are of long type (eight bytes)
ATDB_TABLE This descriptor points to a table of new
descriptors, possibly including page,
indirect or invalid descriptors.
ATDT_INVALID This descriptor doesn't point to a next
descriptor because it is either a page
descriptor, an early termination descriptor
or invalid.
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This function is used by the mmu.library to scan an already loaded
MMU table.
BUGS
SEE ALSO
RootStarter(), mmu/descriptor.h
mmu.resource/ReadFastDescriptor mmu.resource/ReadFastDescriptor
NAME
ReadFastDescriptor() - read an MMU descriptor quickly.
SYNOPSIS
ReadFastDescriptor( deptr, atd, type, level, ctxt, mmubase );
a1 a0 d0 d1 a5 a6
ReadFastDescriptor( ULONG *, struct AbstractDescriptor *, UBYTE ,
UBYTE, struct IMMUContext *, struct MMUBase *);
FUNCTION
Reads and interprets an MMU table/page descriptor pointed to by
deptr, and fills the abstraction data into the atd.
This is similar to ReadDescriptor except that this function is
allowed to take some shortcuts. It is not assumed to fill in
any property flags or atd->atd_NextType, neither need it work
with long descriptors.
INPUTS
deptr - points to the descriptor to read.
atd - the AbstractDescriptor to be filled in.
type - type of the descriptor to be read. This has the bit
ATDB_LONG set for long descriptors. All other bits
shall be ignored.
level - MMU table level to read the descriptor from. Zero
identifies level A, -1 is used in case this function
shall read and interpret the root pointer itself, as
supplied by RootStarter(). "deptr" points then to a
memory location containing(!) the root pointer.
ctxt - struct IMMUContext this parsing is done within. The
IMMUContext provides all bitmasks to isolate property
bits and pointers from the descriptor, i.e. in
ctxt->ctx_LevelAMask...ctxt->ctx_PageMask. Note that
the LevelAMask is required for reading pointers that
point to a level A table, i.e. the root pointer.
mmubase - pointer to the mmu.library base.
See ReadDescriptor() for further details.
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This streamlined version is used by the mmu.library as soon as
it knows that it works on tables it build itself.
BUGS
SEE ALSO
ReadDescriptor(), mmu/descriptor.h
mmu.resource/CmpDescriptor mmu.resource/CmpDescriptor
NAME
CmpDescriptor() - compare two descriptors by an offset
SYNOPSIS
iseq = CmpDescriptor( descr1 , descr2 , type, delta, mmubase);
ccr a0 a1 d0 d1 a6
void CmpDescriptor( ULONG *, ULONG *, UBYTE, ULONG, struct MMUBase *);
FUNCTION
Compares whether descriptor one is equal to the descriptor up to an
address displacement delta.
Hence, if both descriptors are page descriptors, the call checks
whether the destination page of descr1 equals the destination page
of descr2 minus delta, and whether the properties are identically up
to the MAPP_USED and MAPP_MODIFIED bits.
If both descriptors are indirect, the call checks whether they point
both to the same target descriptor.
If both descriptors are invalid, they are always considered equal.
INPUTS
descr1 - the base descriptor to compare against
descr2 - the descriptor that it is compared with.
type - has ATDT_LONG set for long descriptors, otherwise
descr1 and descr2 point to short descriptors.
has ATDT_INDIRECT set for indirect descriptors.
delta - address displacement of descr2 relative to descr1.
mmubase - base address of the mmu.library
RESULTS
This call returns its result in the condition code register and is
hence not callable from C; note that it is not supposed to be called
by anything but the mmu.library anyhow.
It sets the condition code register Z flag if the descriptors are
considered to be equal, otherwise Z is cleared.
Register a0 must not be touched by this call, and register a1 must
be advanced by one descriptor, i.e. either four or eight bytes,
depending on whether the descriptor is long or short.
This strange syntax was chosen to make the call as fast as possible
and hence to speed up the MMU table scanner.
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This call is used by the mmu.library internal MMU table parser to
detect continously mapped memory blocks. It shall execute as fast
as possible.
BUGS
The calling syntax is ugly.
SEE ALSO
ReadDescriptor()
mmu.resource/IncrementDescriptor mmu.resource/IncrementDescriptor
NAME
IncrementDescriptor() - advance a pointer into an MMU descriptor table
and provide an increment
SYNOPSIS
increment = IncrementDescriptor( atd, index, mmubase );
d0 a0 d0 a6
ULONG IncrementDescriptor( struct AbstractDescriptor *, ULONG,
struct MMUBase *);
FUNCTION
Checks atd->atd_NextType and returns the increment required to
get to the next descriptor; further, loads a pointer at the
descriptor within the descriptor table pointed to by atd->atd_Pointer.
INPUTS
atd - an abstract descriptor describing the start of the descriptor
table and the type of descriptors within this table.
atd->atd_NextType is used to check whether short or long
descriptors are found within this table,
atd->atd_Pointer is assumed to be the base pointer to a
descriptor table of descriptors of type atd->atd_NextType.
index - the index of the descriptor within the table pointed to by
atd->atd_Pointer to provide as secondary output.
mmubase - pointer to the mmu.library base.
RESULTS
increment - the byte increment to get from one descriptor within the
table atd->atd_Pointer points to to the next one. This
is typically four for short and eight for long descriptors.
a0 contains a secondary result that is not useable from C (but note
that this function must not be called by anything but the mmu.library
anyhow), namely the address of the descriptor within the table at
the table entry given by index.
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This call is used by the mmu.library internal MMU table parser to
advance by a table descriptor and to pick a descriptor from a
table.
BUGS
The calling convention is ugly.
SEE ALSO
CmpDescriptor()
mmu.resource/WriteDescriptor mmu.resource/WriteDescriptor
NAME
WriteDescriptor() - build a hardware MMU table descriptor from an
abstract table descriptor.
SYNOPSIS
descr = WriteDescriptor( atd, level, ctxt, mmubase );
d0 a0 d1 a5 a6
ULONG WriteDescriptor( struct AbstractDescriptor *a0, WORD level,
struct IMMUContext *, struct MMUBase *);
FUNCTION
Builds a hardware MMU table descriptor from an abstract description
for a given level of the MMU tree.
INPUTS
atd - AbstractDescriptor providing the information concerning the
descriptor type to build. The following components are
relevant:
atd->atd_Pointer: Either the address of the next
descriptor table for table
descriptors, or the physical address
for page descriptors, or the address
of the destination descriptor for
indirect descriptors, or the
descriptor contents for invalid
descriptors; in the last case, several
bits of the pointer will be masked
out, as they are required to signal an
indirect descriptor type.
atd->atd_Properties: Properties of the descriptor to be
build. MAPP_INVALID or MAPP_SWAPPED
signals that an invalid descriptor
shall be build, MAPP_INDIRECT signals
an indirect descriptor.
atd->atd_LowerLimit: ignored, only short descriptors are
supported
atd->atd_UpperLimit: ignored for the same reason.
atd->atd_ThisType: Descriptor type to build. This must
have the ATDB_LONG bit cleared. The
following types are supported:
ATDT_INVALID Build an invalid descriptor, as if
MAPP_INVALID or MAPP_SWAPPED has been
set. Descriptor contents is within
atd->atd_Pointer.
ATDT_PAGE Build a page descriptor or an early
termination page descriptor. This
reverts to indirect or invalid de-
scriptors if the corresponding
property flags are set. The physical
page address is in atd->atd_Pointer.
In case MAPP_INVALID or MAPP_SWAPPED
are set, atd_Pointer contains the
data for the invalid descriptor.
In case MAPP_INDIRECT is set, the
atd_Pointer contains the address of
the target descriptor.
ATDT_TABLE Build a table descriptor. atd_Pointer
points to the next descriptor table.
ATDT_INDIRECT This value is not allowed. Instead,
indirect descriptors must be build by
MAPP_PAGE and properties of
MAPP_INDIRECT.
atd->atd_NextType ingored.
level - level at which the descriptor shall be build. Level = 0
indicates level A of the MMU tree, level = -1 indicates that
a root descriptor shall be build.
ctxt - pointer to the IMMUContext the descriptor will be part of.
mmubase - pointer to the MMU library base.
RESULTS
descr - the generated descriptor. Note that 0L need not to indicate
an error.
Error conditions are delivered by means of the Z bit of the CCR
register. If the Z bit is one, the requested descriptor could not be
build. This happens for example if a descriptor of type ATDT_PAGE
shall be build at non-page level and the MMU does not support early
termination descriptors. If everything is fine, the Z bit will be
cleared.
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
Note that the usage of the abstract descriptor is slightly different
from that of ReadDescriptor(). ReadDescriptor() delivers a descriptor
type of ATDT_INDIRECT for indirect descriptors, whereas
WriteDescriptor() expects ATDT_PAGE with properties set to
MAPP_INDIRECT to build this descriptor type.
This call is used by the mmu.library table build algorithm to generate
new descriptors.
BUGS
The name is misleading, GenerateDescriptor() would fit better as
this function never writes any descriptor out to memory.
The calling syntax is non-standard and ugly.
SEE ALSO
ReadDescriptor(), mmu/descriptor.h
mmu.resource/FindDescriptor mmu.resource/FindDescriptor
NAME
FindDescriptor() - find an MMU descriptor by logical address.
SYNOPSIS
level = FindDescriptor( addr, ctxt , mmubase );
d0 a0 a5 a6
WORD FindDescriptor( ULONG, struct IMMUContext *, struct MMUBase *);
FUNCTION
This function scans the MMU tables to detect the descriptor that
is responsible for translating the logical address to a physical
address. This descriptor address is returned as secondary result
code in register a0.
For indirect descriptors, this function returns the address
of the descriptor pointing to the target descriptor, and not the
descriptor itself.
The primary result code is the level at which the descriptor
was found. Zero indicates a descriptor at level A of the MMU
table.
INPUTS
addr - logical address whose descriptor shall be found.
ctxt - IMMUContext managing this descriptor.
mmubase - pointer to the mmu.library base.
RESULTS
level - page level the descriptor has been found at. This need
not to be the page level as invalid or early termination
descriptor might abort a table search earlier.
A secondary result is returned in register a0; this is the address
of the descriptor translating the logical address; for indirect
descriptors, this is not the final target descriptor, but the
indirect descriptor pointing to the final target.
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode.
This call has to read MMU descriptors for obvious reasons. As the
mmu.library does not necessarely place these in non-cacheable memory,
your code must keep care to push the descriptors back to memory as
soon as they have been read. Not following this advice may either
cause inconsistent MMU mapping or - even worse - hangs of the MMU.
BUGS
The calling syntax is ugly.
SEE ALSO
mmu.resource/PFlush mmu.resource/PFlush
NAME
PFLush() - flush ATC entries for a given logical address
SYNOPSIS
PFlush( addr, mmubase );
a0 a6
void PFlush( ULONG, struct MMUBase * );
FUNCTION
Flushes the ATC entry for the descriptor describing the mapping
of the passed in logical address.
INPUTS
addr - logical address whose descriptor needs to be flushed.
mmubase - base pointer of the mmu.library
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode.
Since the mmu.library enforces a separate user/supervisor model,
this call must flush the ATC entries for both, user and supervisor
tree.
Note further that early termination descriptors take up more than
one ATC entry. Hence, this call flushes a descriptor for one page,
but not necessarely for all pages it describes.
BUGS
SEE ALSO
PFlushA(), PFlushTwo()
mmu.resource/PFlushA mmu.resource/PFlushA
NAME
PFlushA() - flush the address translation cache completely
SYNOPSIS
PFlushA( mmubase );
a6
void PFlushA( struct MMUBase *);
FUNCTION
Flushes the address translation cache of the MMU completely.
INPUTS
mmubase - library base pointer of the mmu.library
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode.
BUGS
SEE ALSO
PFlush(), PFlushTwo()
mmu.resource/PFlushTwo mmu.resource/PFlushTwo
NAME
PFlushTwo() - flush two descriptors from the ATC
SYNOPSIS
PFlushTwo( addr1, addr2, mmubase);
a2 a3 a6
void PFlushTwo( ULONG, ULONG, struct MMUBase * );
a2 a3 a6
FUNCTION
Flushes two descriptors from the MMU address translation cache by
the logical addresses they describe.
INPUTS
addr1 - first logical address whose descriptor shall be
flushed,
addr2 - second logical address to be flushed
mmubase - base pointer to the mmu.library
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode.
Since the mmu.library enforces a separate user/supervisor model,
this call must flush the ATC entries for both, user and supervisor
tree.
Note further that early termination descriptors take up more than
one ATC entry. Hence, this call flushes a descriptor for one page,
but not necessarely for all pages it describes.
This call does not flush an address range, but really only two
descriptors; this call is used to speed-up the CachePreDMA() and
CachePostDMA() function patches. Otherwise, it is completely
equivalent to calling PFlush() twice with addr1 and addr2 as
arguments, respectively.
BUGS
SEE ALSO
PFlush(), PFlushA()
mmu.resource/PushLine mmu.resource/PushLine
NAME
PushLine() - push a cache line back to memory
SYNOPSIS
PushLine( addr, mmubase );
a0 a6
void PushLine( ULONG, struct MMUBase * );
FUNCTION
Pushes the cache line containing the logical address *a0 back
to memory. Hence, the sixteen-byte block containing the passed
in address will be written out from the cache into memory, if
the corresponding cache line is dirty. The cache line is then
marked as "flushed" and non-valid.
INPUTS
addr - the logical address contained in the cache line to be
pushed.
mmubase - base pointer to the mmu.library base.
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode.
Depending on the cache, this call might require to push more than
just a line; it might also flush the cache completely if this is
more efficient. This call pushes the data cache, and flushes the
instruction cache; hence, it operates on all available caches.
BUGS
SEE ALSO
PushPage(), PushAll(), PushTwo()
mmu.resource/PushPage mmu.resource/PushPage
NAME
PushPage() - push a MMU page back to memory
SYNOPSIS
PushPage( addr, mmubase );
a0 a6
void PushPage( ULONG, struct MMUBase * );
FUNCTION
Pushes the page containing the logical address *a0 back to
memory. Hence, the memory page containing the passed in address
will be written out from the cache into memory, if the
corresponding cache line is dirty. The cache lines are then marked
as "flushed" and non-valid.
INPUTS
addr - the logical address contained in the page to be pushed.
mmubase - base pointer to the mmu.library base.
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode.
Depending on the cache, this call might require to push more than
just a page; it might also flush the cache completely if this is
more efficient. This call pushes the data cache, and flushes the
instruction cache; hence, it operates on all available caches.
BUGS
Due to a hardware bug of the 68060, this call might not flush
the instruction cache as indicated if the address is not
aligned to a page boundary. Hence, you are adviced to align
the address before calling this as the mmu.resource does not
try to work around this bug.
SEE ALSO
PushLine(), PushAll(), PushTwo()
mmu.resource/PushAll mmu.resource/PushAll
NAME
PushAll() - push and flush all caches completely
SYNOPSIS
PushAll( mmubase );
a6
void PushAll( struct MMUBase * );
FUNCTION
Pushes the data cache completely back to memory, and flushes
the data and instruction cache completely.
INPUTS
mmubase - base pointer to the mmu.library base.
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode.
BUGS
SEE ALSO
PushLine(), PushPage(), PushTwo(), exec/CacheClearU()
mmu.resource/PushTwo mmu.resource/PushTwo
NAME
PushTwo() - push two pages of the data cache
SYNOPSIS
PushTwo( addr1, addr2, mmubase );
a2 a3 a6
void PushTwo( ULONG, ULONG, struct MMUBase * );
FUNCTION
Pushes the data cache entries for the pages containing the indicated
logical addresses from out of cache.
INPUTS
addr1 - first logical address contained in the first page to be
pushed,
addr2 - second logical address of the page to be pushed
mmubase - base pointer to the mmu.library
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode.
This call does not touch the instruction cache; its purpose is to
prepare the edges of a memory block that is about to the transfered
by DMA. This is called as part of the CachePreDMA() resp.
CachePostDMA() functions. Note that it doesn't push a range of pages,
but really only to pages.
BUGS
SEE ALSO
PushLine(), PushPage(), PushAll()
mmu.resource/ForbidDMACache mmu.resource/ForbidDMACache
NAME
ForbidDMACache() - forbid caching of a page temporarly as long as an
DMA transfer is running.
SYNOPSIS
ForbidDMACache( addr, ctxt, mmubase );
a0 a5 a6
void ForbidDMACache( ULONG, struct IMMUContext *, struct MMUBase *);
FUNCTION
Increments the DMA cache disable counter for the indicated page and
sets the cache mode of the affected page to MAPP_WRITETRHOUGH until
the matching PermitDMACache() is called. This call nests. Further,
this call must be aware of the user selected page attributes.
INPUTS
addr - a logical address contained in the page to be touched by a
DMA transfer,
ctxt - a struct MMUContext describing the context the corresponding
MMU tree is relative to.
mmubase - library base of the mmu.library
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode. This will be called with all interrupts disabled.
This call must:
- Find the page descriptor for the selected page,
- push it back to memory in case someone read it (illegally, by-
passing the mmu.library functions)
- check the DMA disable counter for the corresponding page.
The mmu.library generates the required counters for you in the
following way: A page-level descriptor table of "N" entries
generates four tables: Table one at offset zero contains the
MMU hardware descriptor, table two at offset "N" contains the
page properties the user selected for the page, or the
"userdata" for invalid or swapped pages, table three at offset
"2*N" contains the DMA disable counters. Table four is still un-
used.
Hence, this call must find the page descriptor of the indicated
page and the size of the page descriptor table. The long word
at byte offset "tablesize * 8" from the page descriptor is the
DMA activity counter, the long word at "tablesize * 4" the
user data or the mapping properties.
- if the DMA disable counter is still zero, and we found a page
descriptor, disable the copyback flag if caching is enabled,
- write the descriptor back to memory,
- push the cache line containing the descriptor to ensure the
MMU will find it.
Note that this call will not work for early termination page
descriptors, invalid, swapped or indirect descriptors. It need
not to work for early termination since the only MMUs that implement
them are the 68851 and 68030 whose CPUs do not offer a copyback
cache and hence do not need this support function. Neither need it
to support invalid or swapped pages since they cannot contain
vital data for a DMA process; it does not support indirect
descriptors since it wouldn't know how to reconstruct them if DMA
is done. This is a documented side condition of DMA and indirect
descriptors that must be kept care of. This function must not crash
if these conditions are not met; it shall not touch the descriptors
then, though.
Note further that the context you get passed in need not to be
the active context; in fact, this function is called with every
available context as soon as a DMA operation is initiated by means
of CachePreDMA() to ensure proper operation even on a context switch
while DMA is active.
This function does nothing in case the MMU does not support copyback,
i.e. for the 68030 and 68851.
BUGS
SEE ALSO
PermitDMACache(), exec/CachePreDMA()
mmu.resource/PermitDMACache mmu.resource/PermitDMACache
NAME
PermitDMACache() - re-enable caching of a page if DMA done
SYNOPSIS
PermitDMACache( addr, ctxt, mmubase );
a0 a5 a6
void PermitDMACache( ULONG, struct IMMUContext *, struct MMUBase *);
FUNCTION
Decrements the DMA cache disable counter for the indicated page and
restores the previously active caching mode if it reaches zero.
This call nests. Further, this call must be aware of the user
selected page attributes.
INPUTS
addr - a logical address contained in the page that was touched by a
DMA transfer,
ctxt - a struct MMUContext describing the context the corresponding
MMU tree is relative to.
mmubase - library base of the mmu.library
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode. This will be called with all interrupts disabled.
This call must:
- Find the page descriptor for the selected page,
- check the DMA disable counter for the corresponding page.
The mmu.library generates the required counters for you in the
following way: A page-level descriptor table of "N" entries
generates four tables: Table one at offset zero contains the
MMU hardware descriptor, table two at offset "N" contains the
page properties the user selected for the page, or the
"userdata" for invalid or swapped pages, table three at offset
"2*N" contains the DMA disable counters. Table four is still un-
used.
Hence, this call must find the page descriptor of the indicated
page and the size of the page descriptor table. The long word
at byte offset "tablesize * 8" from the page descriptor is the
DMA activity counter, the long word at "tablesize * 4" the
user data or the mapping properties.
- decrement the DMA disable counter; if it underruns, it shall
be set back to zero to support faulty devices that report a
DMA-done more than once.
- if the DMA disable counter is zero, proceed as follows:
- push the page descriptor back to memory in case someone touched
it, bypassing the documented mmu.library functions,
- check whether this descriptor is really a page descriptor or
invalid or indirect,
- if it is, check whether the user property flags at offset
"tablesize * 4" indicate copyback caching,
- if so, re-enable the copyback cache.
- push the descriptor back to memory so the MMU will find the
proper descriptor
Note that this call will not work for early termination page
descriptors, invalid, swapped or indirect descriptors. It need
not to work for early termination since the only MMUs that implement
them are the 68851 and 68030 whose CPUs do not offer a copyback
cache and hence do not need this support function. Neither need it
to support invalid or swapped pages since they cannot contain
vital data for a DMA process; it does not support indirect
descriptors since it wouldn't know how to reconstruct them if DMA
is done. This is a documented side condition of DMA and indirect
descriptors that must be kept care of. This function must not crash
if these conditions are not met; it shall not touch the descriptors
then, though.
Note further that the context you get passed in need not to be
the active context; in fact, this function is called with every
available context as soon as a DMA operation is terminated by means
of CachePostDMA() to ensure proper operation even on a context switch
while DMA is active.
This function does nothing in case the MMU does not support copyback,
i.e. for the 68030 and 68851.
BUGS
SEE ALSO
ForbidDMACache(), exec/CachePostDMA()
mmu.resource/InstallPage mmu.resource/InstallPage
NAME
InstallPage() - re-install a page descriptor into the MMU tree
SYNOPSIS
InstallPage( level, tablesize, dest, descr, data, addr, ctxt, mmubase);
d2 d1 a2 d0 d4 a0 a5 a6
void InstallPage( WORD, ULONG, ULONG *, ULONG, ULONG, ULONG,
struct IMMUContext *, struct MMUBase *);
FUNCTION
Re-install a page descriptor into a MMU tree; keep care about DMA
disable counters and carry the used/modified bits over from the last
descriptor. Install or modify page data, adjust the context.
INPUTS
level - level of the MMU tree where the descriptor shall be
installed. Zero is level A.
tablesize - size of the descriptor table at this level in entries
dest - physical address where to install the descriptor to
descr - the descriptor to install
data - secondary page data to install
addr - logical address that is described by this descriptor
ctxt - struct IMMUContext this descriptor is part of
mmubase - library base pointer of the mmu.library
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode. This will be called with all interrupts disabled.
This call must:
- check whether we need to install at page level; if so, DMA disable
counters are available at byte offset "tablesize * 8" from the
descriptor destination address "dest".
- if the DMA counter is found active, the descriptor is found to be
a valid page descriptor with copyback enabled, copyback must be
disabled. This is required for proper support of ForbidDMACache()
as the user may want to install a descriptor while a DMA operation
is running on the same page.
- secondary page data must be written to byte offset "tablesize * 4"
from "dest". This page data consists either of the "property flags"
if the page descriptor is valid or indirect, or on the "user data"
for invalid or swapped non-repairable pages.
- check again whether the descriptor is a valid page descriptor;
- if so, check the type of the old descriptor; if it is a page
descriptor, too, carry its USED/MODIFIED bits over to the new
descriptor. If it is a table descriptor, carry its MODIFIED bit
over. This step is required to keep the U/M bits consistent in case
the user wants to install a new descriptor while pages haven't been
swapped out/read out yet.
- write the new descriptor back to memory.
- push the cache line containing the new descriptor so the MMU will
really find it.
- check whether the logical address that is maintained by this
descriptor is the zero-page; if so, the descriptor address must be
placed in ctxt->ctx_ZeroPage for the exception handler
Note that the context you get passed in need not to be the active
context.
Note further that this call expects a valid page descriptor active
already; in case you want to install a page descriptor into a not
yet valid array of descriptors, use InstallNewPage() instead.
BUGS
SEE ALSO
InstallNewPage(), ForbidDMACache()
mmu.resource/InstallNewPage mmu.resource/InstallNewPage
NAME
InstallNewPage() - Install a page descriptor into the MMU tree
SYNOPSIS
InstallNewPage( level, tablesize, dest, descr, data, addr, ctxt, mmubase);
d2 d1 a2 d0 d4 a0 a5 a6
void InstallNewPage( WORD, ULONG, ULONG *, ULONG, ULONG, ULONG,
struct IMMUContext *, struct MMUBase *);
FUNCTION
Install a page descriptor into a MMU tree; keep care about DMA
disable counters. Install new page data, adjust the context.
INPUTS
level - level of the MMU tree where the descriptor shall be
installed. Zero is level A.
tablesize - size of the descriptor table at this level in entries
dest - physical address where to install the descriptor to
descr - the descriptor to install
data - secondary page data to install
addr - logical address that is described by this descriptor
ctxt - struct IMMUContext this descriptor is part of
mmubase - library base pointer of the mmu.library
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode. This will be called with all interrupts disabled.
This call must:
- check whether we need to install at page level; if so, DMA disable
counters are available at byte offset "tablesize * 8" from the
descriptor destination address "dest".
- if the DMA counter is found active, the descriptor is found to be
a valid page descriptor with copyback enabled, copyback must be
disabled. This is required for proper support of ForbidDMACache()
as the user may want to install a descriptor while a DMA operation
is running on the same page.
- secondary page data must be written to byte offset "tablesize * 4"
from "dest". This page data consists either of the "property flags"
if the page descriptor is valid or indirect, or on the "user data"
for invalid or swapped non-repairable pages.
- write the new descriptor back to memory.
- push the cache line containing the new descriptor so the MMU will
really find it.
- check whether the logical address that is maintained by this
descriptor is the zero-page; if so, the descriptor address must be
placed in ctxt->ctx_ZeroPage for the exception handler
Note that the context you get passed in need not to be the active
context.
This call does not make any assumptions about the contents of
"dest"; therefore, it does not try to carry over the USED/MODIFIED
bits from there and their contents will be lost resp. replaced by
the contents of the new descriptor. Do not use this call in case
you want to replace an already active page descriptor, consider
InstallPage() instead.
BUGS
SEE ALSO
InstallPage(), ForbidDMACache()
mmu.resource/ReadUMFlags mmu.resource/ReadUMFlags
NAME
ReadUMFlags() - read and reset the USED/MODIFIED flags
SYNOPSIS
flags = ReadUMFlags( descr, level, ctxt, mmubase );
a0 d0 a5 a6
ULONG ReadUMFlags( ULONG *, WORD, struct IMMUContext *,
struct MMUBase *);
FUNCTION
Reads the USED/MODIFIED flags of the indicated descriptor, returns
them and clears them in the descriptor for the next go. This call
shall be used to drive a virtual memory engine.
INPUTS
descr - address of the descriptor to be read
level - level of the descriptor within the MMU tree. Level A
is indicated by zero.
ctxt - pointer to the IMMUContext this descriptor is part of.
mmubase - base of the mmu.library
RESULTS
a combination of MAPP_USED and/or MAPP_MODIFIED depending on whether
the memory page handled by the descriptor has been read, or touched
since the last call of this function or InstallNewPage().
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode. This will be called with all interrupts disabled.
This call must:
- check whether the descriptor is a page or a table descriptor or
invalid or indirect. Table descriptors only carry the USED and
not the MODIFIED bit; invalid or indirect descriptors do not carry
any status information.
- read the descriptor and extract the apropriate bits. These are
no bits at all for indirect or invalid descriptors.
- push the cache line containing the descriptor back to memory.
BUGS
SEE ALSO
InstallNewPage()
mmu.resource/SetIndirect mmu.resource/SetIndirect
NAME
SetIndirect() - install an indirect page descriptor
SYNOPSIS
SetIndirect( where, logical, descr, mmubase );
a0 a1 d0 a6
void SetIndirect( ULONG *, ULONG, ULONG, struct MMUBase * );
FUNCTION
Installs a new user-generated indirect descriptor at the
supplied address and flushes the caches accordingly.
INPUTS
where - physical address into which the descriptor shall go
logical - logical address of the page that is handled by the
descriptor or (ULONG)(~0) if it handles more than
one or an unknown logical address
descr - the descriptor to install
mmubase - base of the mmu.library
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode.
This call
- checks the logical address against ~0. If it is, the ATC is
flushed completely, the descriptor is installed, and the
cache line containing the ATC is pushed, too.
- if it is not, only the ATC for the target logical address is
pushed, the descriptor is installed, the cache line is pushed,
and the ATC is flushed again.
BUGS
SEE ALSO
SetIndirectArray()
mmu.resource/SetIndirectArray mmu.resource/SetIndirectArray
NAME
SetIndirectArray() - install an array of indirect descriptors at once
SYNOPSIS
SetIndirectArray ( where, descr, num , mmubase );
a0 a1 d0 a6
void SetIndirectArray ( ULONG *, ULONG *, ULONG, struct MMUBase *);
FUNCTION
Installs an array of user generated descriptors at once and handles
caches accordingly.
INPUTS
where - physical destination address where the descriptors
shall go
descr - logical address of the source array to take the
descriptors from
num - number of descriptors to install, i.e. size of the
array in entries
mmubase - base address of the mmu.library
RESULTS
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode.
This call shall try to find the most efficient way to install the
passed descriptors; for example, it might want to install as many
descriptors at once before pushing their cache lines; this call
must also flush the ATC when done.
BUGS
SEE ALSO
SetIndirect()
mmu.resource/WithoutMMU mmu.resource/WithoutMMU
NAME
WithoutMMU() - call a small user interface with the MMU disabled
SYNOPSIS
res = WithoutMMU( userprocptr, mmubase );
d0 a5 a6
ULONG WithoutMMU( APTR userproc, struct MMUBase *);
FUNCTION
Calls the supplied user routine with the MMU and all interrupts
disabled; the user routine must return with RTS and may provide
a result code in register d0 that is passed out again.
INPUTS
userprocptr - physical address of the user routine to be
called
mmubase - base address of the mmu.library
RESULTS
res - whatever was left in regster d0 by the user routine.
NOTES
Note that a6 points to the mmu.library base, not to the resource
base.
This is always called from supervisor mode; do not attempt to call
it from user mode.
This routine is, in fact, completely register transparent; it
returns all the registers that the user routine left in the CPU.
Note however that the user routine might not be able to do very
much: Due to the disabled MMU, some system structures, or even the
complete Os might be absent.
The implementation is required to save back some of the MMU state,
push all caches, disable the interrupts and the MMU, call the user
function, flush the ATC and caches, and restore the MMU state again.
It must not touch any registers - or rather, must restore them if it
does.
BUGS
Requires at least the supervisor stack to map the same with and
without the MMU. There is no much hope otherwise.
SEE ALSO
mmu/WithoutMMU()
mmu.resource/Exception mmu.resource/Exception
NAME
Exception() - Handle a bus error exception
SYNOPSIS
Exception();
Exception();
FUNCTION
This is the complete access error handler of the MMU/CPU combination
that is handled by this mmu.resource. You must not call this function;
rather, the mmu.library will install the function vector of this
routine directly into the vector base of the CPU. It is the job of this
routine to supply the ExceptionData structure to user exception
handlers, to provide suitable access to the CPU pipelines or provide an
emulation thereof, and to emulate accesses into the zero page,
including AbsExecBase, if the active context allows so.
All this makes this function maybe the most trickiest one of the
mmu.library combo.
INPUTS
None, except the complete MMU/CPU status when this is called on a
bus error. Note that this routine gets no pointer to the mmu.library
passed in, even though it is required. Use CheckMMUInterface()
above to keep a local copy of the library base somewhere as it is
needed.
RESULTS
None, except that the provided user exception handlers must be
handled consistently; if none of them is willing to accept this
access error, the system access error handler must be invoked,
causing the infamous "Guru".
NOTES
This is the beasty one.
This function shall do the following:
- Check for the special branch cache prediction error for the 68060.
If found active, the branch cache must be flushed.
- Fetch the active context from the mmu.library base. Check whether
this is a user or supervisor access, select the proper context.
- Check for long-word reads from AbsExecBase; if found, and the
context allows these reads, provide a cached copy of AbsExecBase.
Do *NOT* attempt to read it from the zero page or you end up in an
infinite loop.
Several strategies exist to provide AbsExecBase access emulation:
- place it in the CPU input pipeline if the possibility
exists (68020, 68030 only),
- emulate the offending instruction by hand. This is easy
for simple "move.l" cases.
- make the zero page available, enable tracing, let the
access happen, catch the trace exception, disable the
zero page again. The active context contains a pointer
to the zero page descriptor in ctxt->ctx_ZeroPage you
may find useful to modify.
- Check for physical bus error cases or read/modify/write cycles
you need not to handle. If found, restore all registers, and
jump into MMUBase->mulib_OldException(). This will call the system
guru.
- If you decide to handle the access error:
Allocate the ExceptionData structure in
MMUBase->mulib_ExceptionData by setting mmuf_busy in
MMUBase->mulib_Flags1. If you find this bit "on" already,
a double bus fault happened and you better go guru.
- Fill in the ExceptionData structure; keep care about special
cases as MOVE16, MOVEM with predecrement, FMOVE.X, FMOVE.D when
computing the affected logical addresses.
- Check whether the fault goes into the readable part of the
zero page by comparing against ctxt->ctx_LowMemoryLimit. If the
address is larger than this limit, access must be emulated. One
approach to handle this is to enable tracing, enable the zero page
access by modifying the zero page descriptor pointed to by
ctxt->ctx_ZeroPage, re-run the access, catch the trace exception,
disable zero page access again.
- Check for read exceptions. If found, call the following private
function of the mmu.library with the ExceptionData pointer in a0:
fatal = CallExceptionHandlers( excdata );
d0 a0
BOOL CallExceptionHandlers( struct ExceptionData *);
It returns TRUE for a fatal exception; restore registers and
jump into MMULib->mulib_OldException() to invoke the guru.
Otherwise, check ExceptionData->exc_Flags how to continue.
- If (exd_Flags & exdf_call), a user supplied function must be
called in user mode, possibly interrupting your access error
handler. Luckely, no need to mess with this yourself as the
mmu.library can do this for you with the following private
call:
SubUser( excd );
a5
void SubUser( struct ExceptionData *exc );
- If (exd_Flags & exdf_readback), the user provided data for the
CPU pipeline that shall be read. Check for instruction access
errors; if found, go guru and don't try to handle them. Check
for REPAIRABLE as well. If not available, go guru as well.
If you do not have access to the CPU pipeline, you need to emulate
the access to fill the user data: ctxt->ctx_ReadBackPage provides
the physical address of a page that is set aside for this mess.
Fill this page with the user supplied data in the proper alignment,
and modify the descriptor at (not pointed to!)
ctxt->ctx_InvalidIndirect with the proper descriptor. All
"repairable" page descriptors are indirect and point to this
descriptor. Enable tracing, let the access happen - now to the
ctx_ReadBackPage, and catch the trace exception. Disable tracing,
and access to the ReadBackPage, and continue.
- Check for write exceptions. If found, check the properties of
the descriptors that are accessed. If they indicate "MAPP_ROM",
the access must be tolerated without modifying the original page.
If you cannot abort the write by fiddling the CPU pipeline, you
need to provide an emulation again: Replace the involved pages
(at most two due to misalignment) by descriptors pointing to
the two pages at ctx->ctx_RomPages, and keep the original
descriptors in a temporary. Copy original page data over to the
ROM pages of the context, enable tracing, let the access happen.
In the trace exception, restore the original descriptors and
disable tracing.
- Check whether the user likes to see the data that was written
out by checking for MAPP_REPAIRABLE; if so, either try to
supply from the CPU pipeline if available, otherwise you are
in a mess:
- Replace again the pages by the context ROM pages, enable
tracing, store the complete CPU state, let the access happen,
catch the trace exception. Call the user handler/user routines
in here and provide the written out data from the ROM pages
that got modified at the address you recorded before. In case
the user wants to repair the page itself by not setting the
exdf_writecomplete flag in ExceptionData, you are now really in
a mess:
Restore the complete CPU state to what you found during the
access error, restore the descriptors and re-start from the point
where the access error happens.
- If the user does not want the read-out data, call user handlers
and SubUser() within the access error handler directly.
- If the user signaled re-run by not setting exdf_writecomplete,
let the access happen by restoring all registers and running
into an RTE. If not, you still need to provide a destination
where the write goes into; replace the affected descriptors
with the ROM pages of the context, install trace vector,
let the access happen and clean up in the trace exception.
Good luck, I'm with you in spirit.
BUGS
Much more needs to be said about this; the implementation depends
heavely on the CPU/MMU programming model, and there are little
general guidelines I can give here. Test carefully!
SEE ALSO
Exception.doc, mmu/context.h